home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1994 January / PSL Monthly Shareware CD-ROM (Public Software Library) (January 1994).iso / games / dos / board / backgam.com / EVAL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1979-11-30  |  11.6 KB  |  527 lines

  1. /*P*/
  2. /****************************************************************/
  3. /*                                */
  4. /* get_pre_command, accept                    */
  5. /*                                */
  6. /* These two routines handle the doubling cube. get_pre_command    */
  7. /* fills in a buffer if a double should be made by the        */
  8. /* person specified (this is the same routine for both black    */
  9. /* and white). Accept returns a char of eother 'Y' or 'N', as    */
  10. /* if the user had typed it in at the terminal.            */
  11. /*                                */
  12. /****************************************************************/
  13.  
  14. #include    <stdio.h>
  15. #include    "bkg.h"
  16.  
  17. get_pre_command( who, buf, owned, value )
  18.  
  19. int    who;
  20. char    buf[];
  21. int    owned, value;
  22.  
  23.     {
  24.  
  25.     int    b_count, w_count, diff, my_count, calc;
  26.  
  27.     buf[ 0 ] = '\0';
  28.  
  29.     /* Only double if the cube is either in the    */
  30.     /* middle, or is my half of the board.        */
  31.  
  32.     if ( ( value < 64        ) &&
  33.          ( ( owned == who      ) ||
  34.            ( owned == NOBODY  ) ) )
  35.         {    
  36.  
  37.         get_counts( who, &b_count, &w_count, &diff, &my_count );
  38.  
  39.         /* If your lead is 7.5% of your count, make    */
  40.         /* a first double. If it is 10.0% make a later    */
  41.         /* double.                    */
  42.  
  43.         calc = ( diff * 100 ) / my_count;
  44.  
  45.         if ( ( value == 1 ) &&
  46.              ( calc >= 8  ) )
  47.             strcpy( buf, "double" );
  48.         else
  49.             if ( calc >= 10 )
  50.                 strcpy( buf, "double" );
  51.  
  52.         } /* look at situation */
  53.  
  54.     } /* get_pre_command */
  55.  
  56. char accept( who )
  57.  
  58.     {
  59.  
  60.     int    b_count, w_count, diff, my_count, calc;
  61.  
  62.     get_counts( who, &b_count, &w_count, &diff, &my_count );
  63.     
  64.     /* Accept a double any time you are less than    */
  65.     /* 15% behind in the game.            */
  66.  
  67.     calc = ( diff * 100 ) / my_count;
  68.  
  69.     if ( calc > -15 )
  70.         return( 'Y' );
  71.     else
  72.         return( 'N' );
  73.  
  74.     } /* accept */
  75.  
  76. /*P*/
  77. /****************************************************************/
  78. /*                                */
  79. /* get_counts                            */
  80. /*                                */
  81. /* Calculate the counts on the board and return these values.    */
  82. /* "who" indicates the player requesting the counts. We return    */
  83. /* that players count in "my_count", and both in the others.    */
  84. /*                                */
  85. /****************************************************************/
  86.  
  87. get_counts( who, b_count, w_count, diff, my_count )
  88.  
  89. int    who, *b_count, *w_count, *diff, *my_count;
  90.  
  91.     {
  92.     
  93.     int    i;
  94.  
  95.     *b_count = *w_count = 0;
  96.  
  97.     for( i = B_BAR; i < 25; i++ )
  98.         *b_count += ( 25 - i ) * board[ i ][ BLACK ];
  99.  
  100.     for( i = W_BAR; i; i-- )
  101.         *w_count += i * board[ i ][ WHITE ];
  102.  
  103.     if ( who == BLACK )
  104.         *diff = *w_count - *b_count;
  105.     else
  106.         *diff = *b_count - *w_count;
  107.  
  108.     *my_count = ( who == WHITE ) ? *w_count : *b_count;
  109.  
  110.     } /* get_count */
  111.  
  112. /*P*/
  113. /****************************************************************/
  114. /*                                */
  115. /* eval                                */
  116. /*                                */
  117. /* These sections control board position evaluation. An integer    */
  118. /* is returned to the caller denoting the worth of a particular    */
  119. /* board. The passed in board is a temp-type, that is, it is    */
  120. /* 3 deep. The [ 2 ] part of the array contains hit men that    */
  121. /* have been removed. If b_eval is called, for example, then    */
  122. /* test[ 15 ][ 2 ] tells if any white men have been bumped off    */
  123. /* of the 15 spot.                        */
  124. /*                                */
  125. /* It is up to the caller to make sure that the test board was    */
  126. /* "gotten to" via a legal move. See movegen.c for details.    */
  127. /*                                */
  128. /* Needless to say, this is where the "smarts" are. These two    */
  129. /* functions are very critical to a "good" game player. Since    */
  130. /* I'm a 1/2 way good player, I have made these as good as I     */
  131. /* know how; however, there is always room for a lot of late    */
  132. /* improvement by anyone who is more familiar with the "theory"    */
  133. /* than I am (that is just about anyone...).            */
  134. /*                                */
  135. /****************************************************************/
  136.  
  137. /****************************************************************/
  138. /*                                */
  139. /* b_eval                            */
  140. /*                                */
  141. /* Evaluate the test board according to black's favor. Return    */
  142. /* an integer denoting how good the position is. Positive is    */
  143. /* better. The highest eval number is the "best" move.        */
  144. /*                                */
  145. /****************************************************************/
  146.  
  147. b_eval( test, count )
  148.  
  149. int    test[ SIZE ][ 3 ], count;
  150.  
  151.     {
  152.  
  153.     char        buf[ 80 ];
  154.     int        i, j, watch_it, score, quad, end_game, hit_val;
  155.  
  156.     score = 0;
  157.  
  158.     /* If we are heavy into testing, spit    */
  159.     /* out the entire board in decimal.    */
  160.  
  161.     if ( debug == 3 )
  162.         {
  163.         char_at( 21, 0, CTEOL, 0x07 );
  164.         for( i = 0; i < 26; i++ )
  165.             printf( "%02d ", test[ i ][ WHITE ] );
  166.         char_at( 22, 0, CTEOL, 0x07 );
  167.         for( i = 0; i < 26; i++ )
  168.             printf( "%02d ", test[ i ][ BLACK ] );
  169.         char_at( 23, 0, CTEOL, 0x07 );
  170.         for( i = 0; i < 26; i++ )
  171.             printf( "%02d ", test[ i ][ 2 ] );
  172.         raw_keyboard();
  173.         }
  174.  
  175.     /* Let them know we are still working    */
  176.     /* on a solution...            */
  177.  
  178.     if ( count == 80 )
  179.         write_at( 15, 65, "Thinking...", TEXT_COLOR );
  180.  
  181.     /* Test exception # 0 - we are in the    */
  182.     /* white's inner table, but we're going    */
  183.     /* to lose bad. in that case, we want    */
  184.     /* to hit anything we can!        */
  185.  
  186.     for ( i = 25; i > 10; i-- )
  187.         if ( test[ i ][ WHITE ] )
  188.             break;
  189.  
  190.     if ( i == 10 )
  191.         for ( ; i; i-- )
  192.             if ( test[ i ][ 2 ] )
  193.                 score = 30000;
  194.  
  195.     /* Look for another exception - we may    */
  196.     /* be almost off of the board, but then    */
  197.     /* leave one and only one man open on a    */
  198.     /* particular bar. If that's the case,    */
  199.     /* we don't want to do that...        */
  200.  
  201.     for( i = 24; i > 16; i-- )
  202.         if ( test[ i ][ BLACK ] == 1 )
  203.             break;
  204.  
  205.     if ( i > 16 )
  206.         {
  207.  
  208.         watch_it = FALSE;
  209.  
  210.         for( j = 24; j; j-- )
  211.             if ( test[ j ][ 2 ] )
  212.                 {
  213.                 watch_it = TRUE;
  214.                 break;
  215.                 }
  216.  
  217.         for( j = 25; j > i; j-- )
  218.             if ( test[ j ][ WHITE ] )
  219.                 {
  220.                 watch_it = TRUE;
  221.                 break;
  222.                 }
  223.  
  224.         for( j = 16; j; j-- )
  225.             if ( test[ j ][ BLACK ] )
  226.                 {
  227.                 watch_it = FALSE;
  228.                 break;
  229.                 }
  230.  
  231.         if ( watch_it )
  232.             score = -30000;
  233.  
  234.         } /* exception 1 */
  235.  
  236.     /* Detect the end-game situation.    */
  237.     /* According to a Scientific American    */
  238.     /* article about 5 years ago, this    */
  239.     /* should be a smooth transition, and    */
  240.     /* not a boolean. Future fix?        */
  241.      
  242.     for( i = 1; i < 25; i++ )
  243.         if ( test[ i ][ BLACK ] )
  244.             break;
  245.  
  246.      for( end_game = TRUE; i < 25; i++ )
  247.         if ( ( test[ i ][ WHITE ] ) ||
  248.              ( test[ i ][ 2 ]     ) )
  249.             {
  250.             end_game = FALSE;
  251.             break;
  252.             }
  253.  
  254.     if ( end_game )
  255.         {
  256.  
  257.         for( i = 1; i < 19; i++ )
  258.             score -= test[ i ][ BLACK ] * ( 25 - i );
  259.         for( ; i < 25; i++ )
  260.             score -= test[ i ][ BLACK ];
  261.         return( score );
  262.  
  263.         } /* end_game */
  264.     else
  265.         {
  266.  
  267.         for( i = 24; i; i-- )
  268.             {
  269.  
  270.             quad = ( ( 24 - i ) / 6 ) + 1;
  271.  
  272.             /* If there is only one black player    */
  273.             /* here, then it is a disadvantage. But    */
  274.             /* how much depends on the possability    */
  275.             /* of getting hit, and where it is.    */
  276.  
  277.             if ( test[ i ][ BLACK ] == 1 )
  278.                 {
  279.  
  280.                 /* Check out every potential hitter    */
  281.  
  282.                 hit_val = ( i - 7 );
  283.                 for( j = i + 1; ( j < 26 ) && ( j < i + 12 ); j++ )
  284.                     switch( test[ j ][ WHITE ] )
  285.                         {
  286.  
  287.                         case 0:        break;
  288.  
  289.  
  290.                         case 1:        hit_val += prob[ j - i ];
  291.                                 break;
  292.  
  293.                         case 2:        hit_val += prob[ j - i ] / 2;
  294.                                 break;
  295.  
  296.                         default:    hit_val += prob[ j - i ] * 2;
  297.  
  298.                         } /* switch */
  299.  
  300.                 /* If it's by the outer table, it's    */
  301.                 /* not bad, since we come right back.    */
  302.  
  303.                 score -= hit_val * ( 4 - quad );
  304.  
  305.                 } /* if */
  306.  
  307.             if ( test[ i ][ BLACK ] > 1 )
  308.                 {
  309.                 score += ( i - 7 );
  310.                 score += ( 4 - quad ) * 5;
  311.                 }
  312.  
  313.             /* Hit the white guys?    */
  314.  
  315.             if ( test[ i ][ 2 ] )
  316.                 {
  317.  
  318.                 score += quad * 15;
  319.                 for( j = 24; j > 16; j-- )
  320.                     if ( test[ j ][ BLACK ] > 1 )
  321.                         score += 5;
  322.                     else
  323.                         if ( test[ j ][ BLACK ] == 1 )
  324.                             score -= 3;
  325.  
  326.                 } /* test inner tbl */
  327.  
  328.             } /* for i */
  329.  
  330.         return( score );
  331.  
  332.         } /* not end game */
  333.  
  334.     } /* b_eval */
  335.  
  336. /*P*/
  337. /****************************************************************/
  338. /*                                */
  339. /* w_eval                            */
  340. /*                                */
  341. /* Evaluate the test board according to white's favor. Return    */
  342. /* an integer denoting how good the position is. This should    */
  343. /* be identical to the other one, except that all of the loops    */
  344. /* and values are reversed. Note, though, that taking the neg    */
  345. /* of b_eval is not the same thing! Also, since they should be    */
  346. /* close to the same, it is easy to test changes by making them    */
  347. /* to one or the other evaluator, and letting the machine play    */
  348. /* against itself for 100 games or so (overnight).        */
  349. /*                                */
  350. /****************************************************************/
  351.  
  352. w_eval( test, count )
  353.  
  354. int    test[ SIZE ][ 3 ], count;
  355.  
  356.     {
  357.  
  358.     char        buf[ 80 ];
  359.     int        i, j, watch_it, score, quad, end_game, hit_val;
  360.  
  361.     score = 0;
  362.  
  363.     /* If we are heavy into testing, spit    */
  364.     /* out the entire board in decimal.    */
  365.  
  366.     if ( debug == 3 )
  367.         {
  368.         char_at( 21, 0, CTEOL, 0x07 );
  369.         for( i = 0; i < 26; i++ )
  370.             printf( "%02d ", test[ i ][ WHITE ] );
  371.         char_at( 22, 0, CTEOL, 0x07 );
  372.         for( i = 0; i < 26; i++ )
  373.             printf( "%02d ", test[ i ][ BLACK ] );
  374.         char_at( 23, 0, CTEOL, 0x07 );
  375.         for( i = 0; i < 26; i++ )
  376.             printf( "%02d ", test[ i ][ 2 ] );
  377.         raw_keyboard();
  378.         }
  379.  
  380.     /* Let them know we are still working    */
  381.     /* on a solution...            */
  382.  
  383.     if ( count == 80 )
  384.         write_at( 15, 65, "Hmmm.......", TEXT_COLOR );
  385.  
  386.     /* Test exception # 0 - we are in the    */
  387.     /* black's inner table, but we're going    */
  388.     /* to lose bad. in that case, we want    */
  389.     /* to hit anything we can!        */
  390.  
  391.     for ( i = 0; i < 15; i++ )
  392.         if ( test[ i ][ BLACK ] )
  393.             break;
  394.  
  395.     if ( i == 15 )
  396.         for ( ; i < 25; i++ )
  397.             if ( test[ i ][ 2 ] )
  398.                 score = 30000;
  399.  
  400.     /* Look for another exception - we may    */
  401.     /* be almost off of the board, but then    */
  402.     /* leave one and only one man open on a    */
  403.     /* particular bar. If that's the case,    */
  404.     /* we don't want to do that...        */
  405.  
  406.     for( i = 1; i < 9; i++ )
  407.         if ( test[ i ][ WHITE ] == 1 )
  408.             break;
  409.  
  410.     if ( i < 9 )
  411.         {
  412.  
  413.         watch_it = FALSE;
  414.  
  415.         for( j = 1; j < 25; j++ )
  416.             if ( test[ j ][ 2 ] )
  417.                 {
  418.                 watch_it = TRUE;
  419.                 break;
  420.                 }
  421.  
  422.         for( j = 0; j < i; j++ )
  423.             if ( test[ j ][ BLACK ] )
  424.                 {
  425.                 watch_it = TRUE;
  426.                 break;
  427.                 }
  428.  
  429.         for( j = 9; j < 25; j++ )
  430.             if ( test[ j ][ WHITE ] )
  431.                 {
  432.                 watch_it = FALSE;
  433.                 break;
  434.                 }
  435.  
  436.         if ( watch_it )
  437.             score = -30000;
  438.  
  439.         } /* exception 1 */
  440.  
  441.     /* Detect the end-game situation.    */
  442.  
  443.     for( i = 24; i; i-- )
  444.         if ( test[ i ][ WHITE ] )
  445.             break;
  446.  
  447.     for( end_game = TRUE; i; i-- )
  448.         if ( ( test[ i ][ BLACK ] ) ||
  449.              ( test[ i ][ 2 ]     ) )
  450.             {
  451.             end_game = FALSE;
  452.             break;
  453.             }
  454.  
  455.     if ( end_game )
  456.         {
  457.  
  458.         for( i = 24; i > 6; i-- )
  459.             score -= test[ i ][ WHITE ] * i;
  460.         for( ; i; i-- )
  461.             score -= test[ i ][ WHITE ];
  462.         return( score );
  463.  
  464.         } /* end_game */
  465.     else
  466.         {
  467.  
  468.         for( i = 1; i < 25; i++ )
  469.             {
  470.  
  471.             quad = ( ( i - 1 ) / 6 ) + 1;
  472.  
  473.             if ( test[ i ][ WHITE ] == 1 )
  474.                 {
  475.  
  476.                 hit_val = ( 18 - i );
  477.                 for( j = i - 1; ( j > -1 ) && ( j > i - 12 ); j-- )
  478.                     switch( test[ j ][ BLACK ] )
  479.                         {
  480.  
  481.                         case 0:        break;
  482.  
  483.  
  484.                         case 1:        hit_val += prob[ i - j ];
  485.                                 break;
  486.  
  487.                         case 2:        hit_val += prob[ i - j ] / 2;
  488.                                 break;
  489.  
  490.                         default:    hit_val += prob[ i - j ] * 2;
  491.  
  492.                         } /* switch */
  493.  
  494.                 score -= hit_val * ( 4 - quad );
  495.  
  496.                 } /* if */
  497.  
  498.             if ( test[ i ][ WHITE ] > 1 )
  499.                 {
  500.                 score += ( 18 - i );
  501.                 score += ( 4 - quad ) * 5;
  502.                 }
  503.  
  504.             /* Hit the black guys?    */
  505.  
  506.             if ( test[ i ][ 2 ] )
  507.                 {
  508.  
  509.                 score += quad * 15;
  510.                 for( j = 1; j < 9; j++ )
  511.                     if ( test[ j ][ WHITE ] > 1 )
  512.                         score += 5;
  513.                     else
  514.                         if ( test[ j ][ WHITE ] == 1 )
  515.                             score -= 3;
  516.  
  517.                 } /* test inner tbl */
  518.  
  519.             } /* for i */
  520.  
  521.         return( score );
  522.  
  523.         } /* not end game */
  524.  
  525.     } /* w_eval */
  526.  
  527.